package com.easybbs.controller.base;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotRoleException;
import com.easybbs.entity.enums.ResponseCodeEnum;
import com.easybbs.entity.vo.ResponseVO;
import com.easybbs.exception.BusinessException;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.View;

import javax.servlet.http.HttpServletRequest;
import javax.validation.UnexpectedTypeException;
import java.util.Optional;

@RestControllerAdvice
public class AGlobalExceptionHandlerController extends ABaseController {

    private static final Logger logger = LoggerFactory.getLogger(AGlobalExceptionHandlerController.class);
    private final View error;

    public AGlobalExceptionHandlerController(View error) {
        super();
        this.error = error;
    }

    @ExceptionHandler(value = Exception.class)
    Object handleException(Exception e, HttpServletRequest request) {
        logger.error("请求错误，请求地址{},错误信息:", request.getRequestURL(), e);
        ResponseVO ajaxResponse = new ResponseVO();
        //404
        if (e instanceof NoHandlerFoundException) {
            ajaxResponse.setCode(ResponseCodeEnum.CODE_404.getCode());
            ajaxResponse.setInfo(ResponseCodeEnum.CODE_404.getMsg());
            ajaxResponse.setStatus(STATUC_ERROR);
        } else if (e instanceof NotLoginException) {
            //未登录
            ajaxResponse.setCode(ResponseCodeEnum.CODE_401.getCode());
            ajaxResponse.setInfo(ResponseCodeEnum.CODE_401.getMsg());
            ajaxResponse.setStatus(STATUC_ERROR);
        } else if (e instanceof NotRoleException) {
            //权限不足
            ajaxResponse.setCode(ResponseCodeEnum.CODE_403.getCode());
            ajaxResponse.setInfo(ResponseCodeEnum.CODE_403.getMsg());
            ajaxResponse.setStatus(STATUC_ERROR);
        } else if (e instanceof BusinessException) {
            //业务错误
            BusinessException biz = (BusinessException) e;
            ajaxResponse.setCode(biz.getCode() == null ? ResponseCodeEnum.CODE_600.getCode() : biz.getCode());
            ajaxResponse.setInfo(biz.getMessage());
            ajaxResponse.setStatus(STATUC_ERROR);
        } else if (e instanceof MissingServletRequestParameterException || e instanceof UnexpectedTypeException || e instanceof BindException|| e instanceof MethodArgumentTypeMismatchException) {
            // 请求参数错误
            ajaxResponse.setCode(ResponseCodeEnum.CODE_600.getCode());
            ajaxResponse.setInfo(ResponseCodeEnum.CODE_600.getMsg());
            ajaxResponse.setStatus(STATUC_ERROR);
        } else if (e instanceof DuplicateKeyException) {
            //主键冲突
            ajaxResponse.setCode(ResponseCodeEnum.CODE_601.getCode());
            ajaxResponse.setInfo(ResponseCodeEnum.CODE_601.getMsg());
            ajaxResponse.setStatus(STATUC_ERROR);
        } else {
            ajaxResponse.setCode(ResponseCodeEnum.CODE_500.getCode());
            ajaxResponse.setInfo(ResponseCodeEnum.CODE_500.getMsg());
            ajaxResponse.setStatus(STATUC_ERROR);
        }
        // 参数类型错误记录
        /**
         * else if (e instanceof BindException|| e instanceof MethodArgumentTypeMismatchException) {
         *             //参数类型错误
         *             ajaxResponse.setCode(ResponseCodeEnum.CODE_600.getCode());
         *             ajaxResponse.setInfo(ResponseCodeEnum.CODE_600.getMsg());
         *             ajaxResponse.setStatus(STATUC_ERROR);
         *         }
         */
        return ajaxResponse;
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {

        logger.error("请求错误，请求地址{},错误信息:", request.getRequestURL(), e);
        ResponseVO ajaxResponse = new ResponseVO();
        // 获取BindingResult的错误信息
        BindingResult bindingResult = e.getBindingResult();
        StringBuilder sb = new StringBuilder();
        Optional.ofNullable(bindingResult.getFieldErrors()).ifPresent(errors -> {
            errors.forEach(error -> {
                sb.append(error.getField())
                        .append(":")
                        .append(error.getDefaultMessage())
                        .append(";");
            });
        });
        logger.warn("参数错误：{}", sb.toString());
        ajaxResponse.setCode(ResponseCodeEnum.CODE_600.getCode());
        ajaxResponse.setInfo(sb.toString());
        ajaxResponse.setStatus(STATUC_ERROR);
        return ajaxResponse;
    }
}
